home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Processes / MP Threaded Sort / MPBlitter.c next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  7.6 KB  |  306 lines  |  [TEXT/CWIE]

  1. /*
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    MPBlitter a simple blitter for MP Tasks. 
  5. **
  6. **    by Matthew Xavier Mora, Apple Developer Technical Support
  7. **
  8. **    File:        MPBlitter.c
  9. **
  10. **    Copyright © 1996-1997 Apple Computer, Inc.
  11. **    All rights reserved.
  12. **
  13. **    You may incorporate this sample code into your applications without
  14. **    restriction, though the sample code has been provided "AS IS" and the
  15. **    responsibility for its operation is 100% yours.  However, what you are
  16. **    not permitted to do is to redistribute the source as "DSC Sample Code"
  17. **    after having made changes. If you're going to re-distribute the source,
  18. **    we require that you make it clear in the source that the code was
  19. **    descended from Apple Sample Code, but that you've made changes.
  20. */
  21.  
  22. /* 
  23.     This is a simple blitter to allow my MPtask to blit to the screen.
  24.     I was going to add masked blitting that honored the visRgn and clip
  25.     regions so that it didn't color outside the lines. I haven't done that 
  26.     yet. 
  27.  
  28.     Since the original SortPicts program that I used only works with 
  29.       8 bit images I didn't spend any time adding any other cases to the 
  30.     blitter. If I ever get time I'll finish the blitter to be more useful
  31.     as a generic CopyBits routine for MP.
  32.  
  33. */
  34.  
  35. #include "MPBlitter.h"
  36. #include <Multiprocessing.h>
  37.  
  38. //-----------------------------------------------------------------------------------
  39. pascal void MPCopyBits(BitMapPtr srcBits, BitMapPtr dstBits, Rect *srcRect, Rect *dstRect,short mode, RgnHandle mask)
  40. //-----------------------------------------------------------------------------------
  41. {
  42. #pragma unused (mode)
  43.     PixMapPtr            srcPM;
  44.     PixMapPtr            dstPM;
  45.     long                dstLeft;
  46.     long                dstRight;
  47.     long                srcLeft;
  48.     long                srcRowBytes;
  49.     long                dstRowBytes;
  50.     char *                srcRow;
  51.     char *                dstRow;
  52.     char *                srcPtr;
  53.     char *                dstPtr;
  54.     long                 height;
  55.     long                width;
  56.     long                 i;
  57.     long                offset;
  58.     MPCriticalRegionID    blitterBusy;
  59.     
  60.     blitterBusy = (MPCriticalRegionID)mask;
  61.     (void)MPEnterCriticalRegion(blitterBusy, kDurationForever);
  62.  
  63.     if (dstRect->top == dstRect->bottom) {
  64.         // a simple flag to say that the image is not ready
  65.         goto exit;
  66.     }     
  67.     srcPM = (PixMapPtr) srcBits;
  68.     dstPM = (PixMapPtr) dstBits;
  69.      
  70.     srcRow = (char *) srcPM->baseAddr;
  71.     dstRow = (char *) dstPM->baseAddr;
  72.  
  73.     srcRowBytes = (srcPM->rowBytes & 0x3fff);
  74.     dstRowBytes = (dstPM->rowBytes & 0x3fff);
  75.  
  76.     // get the bit offset to the src left edge
  77.     srcLeft = srcRect->left - srcPM->bounds.left;
  78.     srcLeft *= srcPM->pixelSize;
  79.     srcRow += srcLeft;
  80.  
  81.     // get the bit offset to the dst left and right edges
  82.     dstLeft = dstRect->left - dstPM->bounds.left;
  83.     dstLeft *= dstPM->pixelSize;
  84.     dstRight = dstRect->right - dstPM->bounds.left;
  85.     dstRight *= dstPM->pixelSize;
  86.     dstRow += dstLeft >> 3;
  87.         
  88.     // offset the src and dst ptrs to the first row
  89.     offset = srcRect->top - srcPM->bounds.top;
  90.     offset *= srcRowBytes  ;
  91.     srcRow += offset;
  92.  
  93.     offset = dstRect->top - dstPM->bounds.top;
  94.     offset *= dstRowBytes ;
  95.     dstRow += offset;
  96.  
  97.     height = dstRect->bottom - dstRect->top - 1;
  98.     width = dstRect->right - dstRect->left - 1;
  99.     width *= (dstPM->pixelSize >> 3);
  100.  
  101.     if (srcPM->pixelSize != dstPM->pixelSize) {
  102.         // ACK!
  103.     }
  104.     switch (dstPM->pixelSize) {
  105.         case 8:
  106.             while (height--) {
  107.                 srcPtr = srcRow;
  108.                 dstPtr = dstRow;
  109.                 
  110.                 for (i = 0 ;i < width >> 2;i++) 
  111.                 {
  112.                     *dstPtr  = *srcPtr;
  113.                     ++srcPtr;
  114.                     ++dstPtr;
  115.                     *dstPtr  = *srcPtr;
  116.                     ++srcPtr;
  117.                     ++dstPtr;
  118.                     
  119.                     *dstPtr  = *srcPtr;
  120.                     ++srcPtr;
  121.                     ++dstPtr;
  122.                     
  123.                     *dstPtr  = *srcPtr;
  124.                     ++srcPtr;
  125.                     ++dstPtr;                            
  126.                 }
  127.  
  128.                 switch ( width % 4) {
  129.                     case 3:
  130.                     *dstPtr  = *srcPtr;
  131.                     ++srcPtr;
  132.                     ++dstPtr;                    
  133.                     case 2:
  134.                     *dstPtr  = *srcPtr;
  135.                     ++srcPtr;
  136.                     ++dstPtr;                    
  137.                     case 1:
  138.                     *dstPtr  = *srcPtr;
  139.                     ++srcPtr;
  140.                     ++dstPtr;                    
  141.                     
  142.                 }
  143.                 srcRow +=  srcRowBytes;
  144.                 dstRow +=  dstRowBytes;
  145.             }
  146.             break;
  147.         case  16:
  148.             break;
  149.         case 32:
  150.             break;
  151.     }
  152.     
  153. exit:
  154.     (void)MPExitCriticalRegion(blitterBusy);
  155. }
  156.  
  157.  
  158. static pascal void CopyBlit(PixMapPtr srcPM, PixMapPtr dstPM, Rect *srcRect, Rect *dstRect)
  159. {
  160.     long            dstLeft;
  161.     long            dstRight;
  162.     long *            srcRow;
  163.     long *            dstRow;
  164.     register long *    srcPtr;
  165.     register long *    dstPtr;
  166.     long            leftMask;
  167.     long            notLeftMask;
  168.     long            rightMask;
  169.     long            notRightMask;
  170.     long            dstLong;
  171.     short            dstLongs;
  172.     short            localheight;// = height;
  173.     long            offset;
  174.     long            timesCopy;
  175.     
  176.      short    height;
  177.      long        srcRowBytes;
  178.      long        dstRowBytes;
  179.      long        srcLeft;
  180.     
  181.     localheight = height = srcRect->bottom - srcRect->top;    // No scaling allowed
  182.     
  183.     srcRowBytes = srcPM->rowBytes & 0x3fff;
  184.     dstRowBytes = dstPM->rowBytes & 0x3fff;
  185.     
  186.     // get the bit offset to the src left edge
  187.     srcLeft = (srcRect->left - srcPM->bounds.left) * srcPM->pixelSize;
  188.  
  189.     srcRow = (long *) srcPM->baseAddr;
  190.     dstRow = (long *) dstPM->baseAddr;
  191.         
  192.     // offset the src ptr to the first long
  193.     srcRow += srcLeft >> 5;
  194.     
  195.     // get the bit offset to the dst left and right edges
  196.     dstLeft = (dstRect->left - dstPM->bounds.left) * dstPM->pixelSize;
  197.     dstRight = (dstRect->right - dstPM->bounds.left) * dstPM->pixelSize;
  198.     
  199.     // get the number of middle longs to do minus the left edge long
  200.     dstLongs = ((dstRight - dstLeft) >> 5) - 1;
  201.     
  202.     // offset the dst Ptr to the first long
  203.     dstRow += dstLeft >> 5;
  204.  
  205.     // now compute left and right masks for the dst
  206.     dstLeft &= 0x1f;
  207.     leftMask = ( 1 << dstLeft ) - 1;
  208.     notLeftMask = ~leftMask;
  209.     
  210.     dstRight &= 0x1f;
  211.     notRightMask = ( 1 << dstRight ) - 1;
  212.     rightMask = ~notRightMask;
  213.     
  214.     // offset the src and dst ptrs to the first row
  215.     offset = (srcRect->top - srcPM->bounds.top) * srcRowBytes;
  216.     srcRow +=  offset >> 2;
  217.     
  218.     offset = (dstRect->top - dstPM->bounds.top) * dstRowBytes;
  219.     dstRow +=  offset >>2;
  220.     
  221.     /* check if we need to do the left and right mask */
  222.     if ( leftMask )
  223.         {
  224.         if ( notLeftMask == 0 )
  225.             {
  226.             leftMask = 0;
  227.             dstLongs++;
  228.             }
  229.         }
  230.         
  231.     if ( rightMask )
  232.         {
  233.         if ( notRightMask == 0 )
  234.             {
  235.             rightMask = 0;
  236.             dstLongs++;
  237.             }
  238.         }
  239.         
  240.     //for ( ; localheight >= 0; --localheight )
  241.     // changing the above 'for()' to the below 'while()' is what made this blit routine
  242.     // faster than CopyBits - a speed improvement equal to all other changes I had made
  243.     // previously.  (about 4 to 5 milliseconds, in case you were wondering)
  244.     // Lesson: the true bottlenecks are not always the obvious ones
  245.     while (localheight--)
  246.         {
  247.         srcPtr = srcRow;
  248.         dstPtr = dstRow;
  249.         
  250.         /* do the masked left edge */
  251.         if ( leftMask )
  252.             {
  253.             dstLong = *srcPtr++ & leftMask;
  254.             dstLong |= *dstPtr & notLeftMask;
  255.             *dstPtr++ = dstLong;
  256.             }
  257.  
  258.         /* do the middle longs with Duff's device */
  259.         timesCopy = (dstLongs + 15) >> 4;
  260.         
  261.         switch( dstLongs & 0xF )
  262.             {
  263.             case 0:    do
  264.                     {    *dstPtr++ = *srcPtr++;
  265.             case 15:    *dstPtr++ = *srcPtr++;
  266.             case 14:    *dstPtr++ = *srcPtr++;
  267.             case 13:    *dstPtr++ = *srcPtr++;
  268.             case 12:    *dstPtr++ = *srcPtr++;
  269.             case 11:    *dstPtr++ = *srcPtr++;
  270.             case 10:    *dstPtr++ = *srcPtr++;
  271.             case 9:        *dstPtr++ = *srcPtr++;
  272.             case 8:        *dstPtr++ = *srcPtr++;
  273.             case 7:        *dstPtr++ = *srcPtr++;
  274.             case 6:        *dstPtr++ = *srcPtr++;
  275.             case 5:        *dstPtr++ = *srcPtr++;
  276.             case 4:        *dstPtr++ = *srcPtr++;
  277.             case 3:        *dstPtr++ = *srcPtr++;
  278.             case 2:        *dstPtr++ = *srcPtr++;
  279.             case 1:        *dstPtr++ = *srcPtr++;
  280.                     } while( --timesCopy > 0 );
  281.             }
  282.  
  283.         /* do the masked right edge */
  284.         if ( rightMask )
  285.             {
  286.             dstLong = *srcPtr & rightMask;
  287.             dstLong |= *dstPtr & notRightMask;
  288.             *dstPtr = dstLong;
  289.             }
  290.         
  291.         /* bump to the next row */
  292.         srcRow +=  srcRowBytes >>2;
  293.         dstRow +=  dstRowBytes >>2;
  294.         }
  295.         
  296. }
  297.  
  298. static pascal void betterMPCopyBits(BitMapPtr srcBits, BitMapPtr dstBits,
  299.                 Rect *srcRect, Rect *dstRect, 
  300.                 short mode, RgnHandle mask)
  301. {
  302. #pragma unused (mode,mask)
  303.      CopyBlit((PixMapPtr) srcBits, (PixMapPtr) dstBits,srcRect, dstRect);
  304.      
  305. }
  306.